<template>
  <div class="all">
    <!-- 聊天记录 -->
    <div
      v-MyDraggable="{ handle: '.icon' }"
      class="draggable-window"
      :style="windowStyle"
    >
      <!-- 头部的一些按钮 -->
      <div class="chat-header">
        <svg-icon class="icon" icon-file-name="menu"></svg-icon>
        <span style="font-size: 14px; font-weight: bold">历史记录</span>
        <svg-icon
          class="chat-switch-btn"
          @click="switchImage"
          :icon-file-name="!isExpand ? 'fullscreen' : 'fullscreen-exit'"
        ></svg-icon>
      </div>
      <!-- 内容部分 -->
      <div class="chat-history-content">
        <div class="new-chat" @click="createNewChat">
          <img src="../../assets/logo.png" draggable="false" />
          <span>新的聊天</span>
        </div>
        <div class="chat-list">
          <historical-chat-list
            :isNewChat="isNewChat"
            :historyChatDatas="chatHistoryDatas"
            :currentChatHistoryId="this.chatHistory.chatHistoryId"
            @deleteChatHistory="deleteChat"
            @selectChat="selectChat"
          ></historical-chat-list>
        </div>
      </div>
    </div>
    <div class="chat-container">
      <div class="chat-window" ref="chatWindow">
        <div class="no-new-chat" v-if="!isNewChat">
          <div
            class="message"
            v-for="(message, index) in chatHistory.messages"
            :key="index"
          >
            <div
              :class="{
                'user-message': message.role === 'user',
                'bot-message': message.role === 'assistant',
              }"
              class="message-box"
            >
              <el-avatar
                style="background-color: #f4f4f4"
                v-if="message.role === 'assistant'"
                :size="40"
                :src="require('../../assets/logo.png')"
              ></el-avatar>
              <div
                :class="{
                  'message-content-user': message.role === 'user',
                  'message-content-bot': message.role === 'assistant',
                }"
                class="message-content"
                v-html="renderMarkdown(message.content)"
              ></div>
              <el-avatar
                v-if="message.role === 'user'"
                :size="40"
                :src="userInfo.imgUrl"
              ></el-avatar>
            </div>
          </div>
        </div>
        <div class="new-chat" v-else>
          <img
            src="../../assets/logo.png"
            draggable="false"
            style="width: 120px; height: 120px; border-radius: 50%"
          />
          <span class="welcome-message"
            >欢迎来到写作助手! 您需要我提供什么帮助?</span
          >
        </div>
      </div>
      <div class="input-container">
        <textarea
          ref="inputBox"
          class="input-box"
          v-model="newMessage"
          @input="autoResize"
          @keydown.enter.exact.prevent="sendMessage"
          @keydown.enter.shift.exact="() => {}"
          placeholder="描述你的问题"
        ></textarea>
        <send-btn :disabled="isButtonDisabled" @click="sendMessage" />
      </div>
    </div>
  </div>
</template>

<script>
import { mapState } from "vuex";
import MarkdownIt from "markdown-it";
import hljs from "highlight.js";
import "highlight.js/styles/agate.css"; // 导入样式
import Clipboard from "clipboard";
import OpenAI from "openai";
import SendBtn from "../../components/UIVerse/SendBtn.vue";
import {
  saveChatHistory,
  updateChatHistoryMessages,
  getChatHistoryByUserId,
} from "../../api/AIChatView";
import { getUserId } from "../../utils/auth";
import MyDraggable from "../../directives/draggable";
import HistoricalChatList from "./components/HistoricalChatList.vue";
export default {
  // 自定义指令
  directives: {
    MyDraggable,
  },
  components: {
    SendBtn,
    HistoricalChatList,
  },
  data() {
    return {
      topValue: 0,
      leftValue: 0,
      // 当前聊天记录id
      chatHistoryDatas: [],
      chatHistory: {
        chatHistoryId: null,
        chatTitle: "",
        userId: getUserId(),
        chatDate: "",
        // 聊天记录
        messages: [],
      },
      // 聊天记录是否展开
      isExpand: false,
      // 聊天框
      windowSize: {
        width: 230,
        height: 22,
      },
      // 发送按钮是否禁用
      isButtonDisabled: false,
      // 判断是否是新聊天
      isNewChat: true,
      // openai的初始化变量
      openai: null,
      // 用户输入的信息
      newMessage: "",
      // 代码复制处理
      clipboard: "",
      // 代码高亮处理
      md: new MarkdownIt({
        html: true,
        linkify: true,
        typographer: true,
        highlight: function (str, lang) {
          // 当前时间加随机数生成唯一的id标识
          const codeIndex =
            parseInt(Date.now()) + Math.floor(Math.random() * 10000000);
          const linesLength = str.split(/\n/).length - 1;
          let html = `<button class="copy-btn" type="button" data-clipboard-action="copy" data-clipboard-target="#copy${codeIndex}">复制</button>`;
          if (lang && hljs.getLanguage(lang)) {
            try {
              // highlight.js 高亮代码
              const preCode = hljs.highlight(lang, str, true).value;
              html = html + preCode;
              if (linesLength) {
                html += '<b class="name">' + lang + "</b>";
              }
              // 将代码包裹在 textarea 中
              return `<pre class="hljs"><code>${html}</code></pre><textarea style="position: absolute;top: -9999px;left: -9999px;z-index: -9999;" id="copy${codeIndex}">${str.replace(
                /<\/textarea>/g,
                "&lt;/textarea>"
              )}</textarea>`;
            } catch (error) {
              console.log(error);
            }
          }
          return `<pre class="hljs"><code>${html}</code></pre><textarea style="position: absolute;top: -9999px;left: -9999px;z-index: -9999;" id="copy${codeIndex}">${str.replace(
            /<\/textarea>/g,
            "&lt;/textarea>"
          )}</textarea>`;
        },
      }),
    };
  },
  methods: {
    // 选择了聊天记录
    selectChat(chat) {
      this.chatHistory = chat;
      this.isNewChat = false;
    },
    // 找到这条记录并把它删除
    deleteChat(chatHistoryId) {
      this.chatHistoryDatas = this.chatHistoryDatas.filter(
        (item) => item.chatHistoryId !== chatHistoryId
      );
    },
    // 文本框高度
    autoResize() {
      const textarea = this.$refs.inputBox;
      textarea.style.height = "20px";
      textarea.style.height = Math.min(textarea.scrollHeight - 20, 70) + "px";
    },
    // markdown
    renderMarkdown(content) {
      return this.md.render(content);
    },
    // 确保滚动条在底部
    scrollToBottom() {
      const chatWindow = this.$refs.chatWindow;
      chatWindow.scrollTop = chatWindow.scrollHeight;
    },
    // 发送信息按钮
    async sendMessage() {
      if (this.newMessage.trim() === "") {
        // 发送信息不能为空
        this.$message.error("发送信息不能为空！");
        return;
      }
      // 文本框高度自适应
      const textarea = this.$refs.inputBox;
      textarea.style.height = "20px";

      this.isNewChat = false;
      // 将消息添加到聊天记录中
      this.chatHistory.messages.push({
        role: "user",
        content: this.newMessage,
      });
      this.newMessage = "";

      // 清空输入框后立即显示用户消息
      await this.$nextTick();
      this.scrollToBottom();

      // 模拟流式响应
      this.simulateBotResponse();
    },
    async simulateBotResponse() {
      this.isButtonDisabled = true; // 禁用发送按钮
      try {
        const stream = await this.openai.beta.threads.createAndRun({
          assistant_id: "asst_7EhOILdPWkNg3lWIWyY6lOwR",
          thread: {
            messages: this.chatHistory.messages,
          },
          stream: true,
        });

        let currentMessage = { role: "assistant", content: "" }; // 初始化一个新的消息对象
        this.chatHistory.messages.push(currentMessage); // 将这个新消息对象添加到消息列表中

        for await (const event of stream) {
          if (event.event === "thread.message.delta") {
            const content = event.data.delta.content[0].text.value || "";
            if (content) {
              currentMessage.content += content; // 追加内容到当前消息
              await this.$nextTick(); // 更新视图
              this.scrollToBottom();
            }
          }
        }
        // 保存或更新聊天记录
        if (this.chatHistory.chatHistoryId === null) {
          // 将对话转换为文本格式
          const dialogueText = this.chatHistory.messages
            .map((message) => `${message.role}: ${message.content}`)
            .join("\n");
          // 构建请求的消息体--标题
          const prompt = `根据以下对话生成一个约6字的标题:\n${dialogueText}`;
          const chatTitle = await this.openai.chat.completions.create({
            messages: [{ role: "system", content: prompt }],
            model: "gpt-4o-mini",
            max_tokens: 20,
            temperature: 0.7,
            top_p: 1.0,
          });
          // 生成的标题
          this.chatHistory.chatTitle = chatTitle.choices[0].message.content;
          // 将聊天记录转为String
          const messagesString = JSON.stringify(this.chatHistory.messages);
          // 构建请求的消息体
          const requestBody = {
            userId: getUserId(),
            chatTitle: this.chatHistory.chatTitle,
            messages: messagesString,
          };
          // 保存聊天记录
          saveChatHistory(requestBody).then((res) => {
            if (res.data.code === 1) {
              // 将返回的数据插入列表中
              this.chatHistory.chatHistoryId = res.data.data.chatHistoryId;
              this.chatHistory.chatDate = res.data.data.chatDate;
              this.chatHistory.isDisabled = true;
              this.chatHistoryDatas.unshift(this.chatHistory);
            } else {
              this.$message.error("网络错误");
            }
          });
        } else {
          // 更新聊天记录
          updateChatHistoryMessages({
            ...this.chatHistory,
            messages: JSON.stringify(this.chatHistory.messages),
          }).then((res) => {
            if (res.data.code === 1) {
              res;
            } else {
              this.$message.error("网络错误");
            }
          });
        }
      } catch (error) {
        console.error("Error:", error);
      }
      this.isButtonDisabled = false; // 启用发送按钮
    },
    // 获取聊天记录
    getChatHistoryByUserId() {
      getChatHistoryByUserId(getUserId()).then((res) => {
        if (res.data.code === 1) {
          const chatHistories = res.data.data.map((history) => {
            // 解析 messages 字段
            history.messages = JSON.parse(history.messages);
            history.isDisabled = true;
            return history;
          });
          this.chatHistoryDatas = chatHistories;
          // this.chatHistory = chatHistories[6];
          // this.isNewChat = false;
        } else {
          this.$message.error("网络错误");
        }
      });
    },
    // 历史记录的展开收起事件
    switchImage() {
      this.isExpand = !this.isExpand;
      if (!this.isExpand) {
        this.windowSize.height = 22;
      } else {
        this.windowSize.height = 500;
      }
    },
    // 发起新的聊天
    createNewChat() {
      this.getChatHistoryByUserId();
      if (!this.isNewChat) {
        this.isNewChat = true;
        this.chatHistory.messages = [];
        this.chatHistory.chatHistoryId = null;
        this.chatHistory.chatTitle = "";
        this.chatHistory.chatDate = "";
        this.chatHistory.studentId = getUserId();
        this.newMessage = "";
        this.isButtonDisabled = false;
      }
    },
  },
  mounted() {
    // 获取聊天记录
    this.getChatHistoryByUserId();
    // 复制提示
    this.$nextTick(() => {
      this.clipboard = new Clipboard(".copy-btn");
      // 复制成功失败的提示
      this.clipboard.on("success", (e) => {
        e;
        this.$notify({
          title: "成功",
          message: "复制成功",
          type: "success",
        });
      });
      this.clipboard.on("error", (e) => {
        e, this.$message.error("复制失败");
      });
    });
    // ai初始化
    this.openai = new OpenAI({
      apiKey: process.env.VUE_APP_OPENAI_API_KEY,
      dangerouslyAllowBrowser: true,
      // 生产环境
      baseURL:
        "https://gateway.ai.cloudflare.com/v1/ba7ce16325c5a5982fc5018ae20c75e8/ruanshelab/openai",
    });
  },
  computed: {
    ...mapState({
      userInfo: (state) => state.userInfo.userInfo,
    }),
    // 历史记录聊天框的高度  即展开或收起
    windowStyle() {
      return {
        width: this.windowSize.width + "px",
        height: this.windowSize.height + "px",
      };
    },
  },
};
</script>

<style lang="less" scoped>
::-webkit-scrollbar {
  width: 3px;
}

::-webkit-scrollbar-track {
  background: #f0f0f0; /* 确保这里的颜色是你想要的 */
  border-radius: 5px;
}

::-webkit-scrollbar-thumb {
  border-radius: 10px;
  background: #888;
}

::-webkit-scrollbar-thumb:hover {
  background: #555;
}
.all {
  position: relative;
  display: flex;
  /* 水平排列 */
  flex-direction: row;
  height: 100%;
  width: 100%;
  .draggable-window {
    background-color: #f0f0f0;
    border: 1px solid #ccc;
    border-radius: 10px;
    padding: 10px;
    left: 3%;
    top: 3%;
    /* 溢出隐藏 */
    overflow: hidden;
    /* 禁止选中文字 */
    user-select: none;
    z-index: 1000;
    .chat-header {
      display: flex;
      justify-content: center;
      align-items: center;
      gap: 25%;
      margin-bottom: 20px;
      .icon {
        transition: transform 0.1s ease, box-shadow 0.1s ease;
      }
      .icon:active {
        transform: scale(0.95);
      }
      .chat-switch-btn {
        float: right;
        float: top;
        cursor: pointer;
        transition: transform 0.1s ease, box-shadow 0.1s ease;
      }
      .chat-switch-btn:active {
        transform: scale(0.95);
      }
    }
    .chat-history-content {
      .new-chat {
        border-radius: 10px;
        display: flex;
        justify-content: center;
        flex-direction: row;
        align-items: center;
        gap: 20px;
        padding: 10px;
        height: 100%;
        overflow-y: auto;
        img {
          border-radius: 50%;
          width: 30px;
          height: 30px;
          user-select: none;
        }
      }
      .new-chat:active {
        transform: scale(0.95);
      }
      .new-chat:hover {
        background-color: #e8e4e4;
      }
      .chat-list {
        max-height: 400px;
      }
    }
  }
  .chat-container {
    display: flex;
    flex-direction: column;
    height: 100%;
    width: 100%;
    overflow: hidden;
    .chat-window {
      padding-top: 20px;
      width: 100%;
      flex: 1;
      overflow-y: auto;
      background-color: #f4f4f4;
      height: 100%;
      .no-new-chat {
        padding: 0 18%;
        .message {
          display: flex;
          margin-bottom: 10px;
          width: 100%;
          .message-box {
            display: flex;
            width: 100%;
            .message-content {
              max-width: 90%;
              padding: 10px;
              background-color: #ffffff;
              color: #000000;
              word-break: break-word;
            }
            .message-content-user {
              margin-top: 20px;
              margin-right: 10px;
              border-top-left-radius: 10px;
              border-bottom-right-radius: 10px;
              max-width: 50%;
              /deep/ p {
                margin: 0 !important;
              }
            }

            .message-content-bot {
              margin-top: 20px;
              margin-left: 10px;
              border-top-right-radius: 10px;
              border-bottom-left-radius: 10px;
              line-height: 25px;
              /deep/ p {
                margin: 0 !important;
              }
            }
          }
          .user-message {
            justify-content: flex-end;
          }
          .bot-message {
            justify-content: flex-start;
          }
        }
      }
      .new-chat {
        height: 100%;
        display: flex;
        /* 居中 */
        flex-direction: column;
        align-items: center;
        img {
          margin-top: 12%;
          user-select: none;
        }
        .welcome-message {
          margin-top: 20px;
          /* 设置字体样式 */
          font-size: 20px;
          font-weight: bold;
          color: #000000;
        }
      }
    }
    .input-container {
      border: 1px solid #ccc;
      border-radius: 15px;
      margin: 0 auto;
      margin-bottom: 40px;
      width: 60%;
      display: flex;
      padding: 5px;
      background-color: #f4f4f4;
      .input-box {
        height: 20px;
        max-height: 80px;
        flex: 1;
        border: none;
        padding: 10px;
        margin-right: 10px;
        font-size: 16px;
        background-color: #f4f4f4;
        outline: none;
        resize: none;
        overflow: auto;
      }
    }
  }
}

.user-message .message-content {
  background-color: #f4f4f4;
  color: #000000;
}
</style>

<style lang="less">
pre {
  width: 95%;
  margin: 20px auto;
  background-color: #000000 !important;
  color: #ffffff !important;
  padding: 15px;
  border-radius: 4px;
}
code {
  font-size: 16px;
}

pre.hljs {
  position: relative;
  overflow: hidden !important;
  code {
    line-height: 25px;
  }
  b.name {
    position: absolute;
    top: 1px;
    right: 50px;
    z-index: 10;
    color: #999;
    pointer-events: none;
  }
  .copy-btn {
    position: absolute;
    top: 5px;
    right: 5px;
    z-index: 10;
    color: #999;
    cursor: pointer;
    background-color: #000000;
    border: 0;
    border-radius: 2px;
  }
  .copy-btn:hover {
    color: #ffffff;
  }
}
</style>
